<template>
    <div>
        <h2>公司关系网络图示例</h2>
        <div id="company-graph" style="width:100%;height:800px;background:#f5f5f5;"></div>
    </div>
</template>
<script setup lang="ts">
defineOptions({ name: 'AntvG6CompanyRelation' });
const FontSize = 16;
import { onMounted } from 'vue';
import { Graph } from '@antv/g6';
const palette = [
    '#5B8FF9', '#5AD8A6', '#F6BD16', '#E8684A', '#6DC8EC',
    '#9270CA', '#FF9D4D', '#269A99', '#FF99C3', '#A9A9A9'
];
// 计算节点size（直径），根据文本长度和换行数自适应
function calcNodeSize(label: string, fontSize = FontSize, padding = 32, maxLineLen = 8, maxLines = 3) {
    // 按maxLineLen分行，最多maxLines行
    const lines = [];
    let i = 0;
    // 将label处理成多行
    while (i < label.length && lines.length < maxLines) {
        lines.push(label.slice(i, i + maxLineLen));
        i += maxLineLen;
    }
    if (i < label.length) {
        lines[lines.length - 1] += '…';
    }
    const maxLineWidth = Math.max(...lines.map(line => line.length));
    // 估算宽度 = 最大行字符数 * 字体宽度 + padding
    const width = maxLineWidth * fontSize - 20;
    // 估算高度 = 行数 * 字体高度 + padding
    const height = lines.length * fontSize * 1.2 + padding;
    // 圆形节点取宽高最大值为直径
    return {
        label: lines.join('\n'),
        size: Math.max(width, height)
    };
}

onMounted(() => {
    // 构造公司关系数据
    const totalCount = 500;
    const allNodes = Array.from({ length: totalCount }).map((_, i) => ({
        id: `mock${i}`,
        label: `模拟公司${i}号节点-测试内容`,
    }));
    // 预处理节点，计算size和换行label
    const allProcessedNodes = allNodes.map((d, i) => {
        const { label, size } = calcNodeSize(d.label, 16, 32, 8, 3);
        return {
            id: d.id,
            label,
            size,
            style: {
                fill: palette[i % palette.length],
                labelText: label,
                labelPlacement: 'center' as const,
                fontSize: FontSize,
                size: size,
                labelTextFill: '#fff',
                labelTextAlign: 'center' as const,
                labelTextBaseline: 'middle' as const,
            }
        };
    });
    // 新增模拟边：每个mock节点与前3个mock节点相连
    const allEdges: any[] = [];
    const mockEdgeStyle = {
        lineWidth: 1,
        labelPlacement: 'center' as const,
        endArrow: true,
        labelBackground: false,
    };
    for (let i = 0; i < allNodes.length; i++) {
        for (let j = 1; j <= 2; j++) {
            if (i - j >= 0) {
                const label = `模拟边${j}`;
                const style = {
                    ...mockEdgeStyle,
                    stroke: allProcessedNodes[i].style.fill,
                    labelText: label,
                };
                allEdges.push({ source: `mock${i}`, target: `mock${i - j}`, label, style });
            }
        }
    }
    // 一次性渲染全部节点和边
    const graph = new Graph({
        container: 'company-graph',
        width: 1200,
        height: 800,
        data: { nodes: allProcessedNodes, edges: allEdges },
        layout: {
            type: 'random',
            preventOverlap: true,
        },
        // behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],
    });
    graph.render();
});
</script> 